package com.jpa.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import com.jpa.security.UserDetailsServiceImpl;

/**
 * 自定义Spring Security认证处理类 需要继承自WebSecurityConfigurerAdapter，重写对应的方法来完成相关的认证处理
 * 
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

	// 依赖注入用户服务类
	@Autowired
	private UserDetailsServiceImpl userService;

	// 依赖注入加密接口
	@Autowired
	private PasswordEncoder passwordEncoder;

	// 依赖注入用户认证接口
	@Autowired
	private AuthenticationProvider authenticationProvider;

	@Autowired
	private DataSource dataSource;

	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
		tokenRepository.setDataSource(dataSource);
		// 启动时创建表，注意，创建好表后，注释掉
		// tokenRepository.setCreateTableOnStartup(true);
		return tokenRepository;
	}

	// spring security提供的加密接口
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	// 认证方式
	@Bean
	public AuthenticationProvider authenticationProvider() {
		logger.info("public AuthenticationProvider authenticationProvider()  ==>");
		// 创建DaoAuthenticationProvider对象
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
		// 不隐藏“用户未找到”异常
		provider.setHideUserNotFoundExceptions(false);
		// 通过重写configure方法添加自定义的认证方式
		provider.setUserDetailsService(userService);
		// 设置密码加密认证
		provider.setPasswordEncoder(passwordEncoder);
		return provider;
	}

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		logger.info("认证方式 ==>public void configure(AuthenticationManagerBuilder auth) throws Exception");
		// 设置认证方式
		auth.authenticationProvider(authenticationProvider);
	}

	/**
	 * .permitAll() 任何人都可访问 
	 * .anyRequest().authenticated() 必须有权限验证 
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		logger.info("权限验证 ==>protected void configure(HttpSecurity http) throws Exception");
		//测试使用   访问：  http://localhost:8080/swagger-ui.html
		http.authorizeRequests().antMatchers("/param").permitAll();
		 
		// 过滤静态资源
		http.authorizeRequests()
				.antMatchers("/","/static/**", "/img/**", "/easyui/**", "/swagger**/**", "/webjars/**", "/v2/**")
				.permitAll()
				.anyRequest().authenticated()
				//访问根目录首页，处理登录
				.and().formLogin().loginPage("/").loginProcessingUrl("/login").permitAll()
				.successHandler(new AuthenticationSuccessHandler() {
					
					@Override
					public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
							Authentication authentication) throws IOException, ServletException {
						//登陆成功重定向地址到/home/index
						response.sendRedirect("/home/index");
					}
				})
				.failureUrl("/login");
		// 注销 
		http.logout().logoutSuccessHandler(new LogoutSuccessHandler() {
			
			@Override
			public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
					throws IOException, ServletException {
				// 注销成功重定向到根目录
				response.sendRedirect("/");
			}
		}).permitAll(); 
		http.csrf().disable(); 
	}
 
}
